/*
 * @Author: panghu chenjh@datamargin.com
 * @Date: 2024-04-15 14:21:39
 * @LastEditors: panghu chenjh@datamargin.com
 * @LastEditTime: 2024-05-04 17:23:18
 * @FilePath: \zheye\src\store\index.ts
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
import { createStore, Commit } from 'vuex'
import request from '@/utils/request'
export interface ResponseType<p> {
  code: number;
  data: p;
  msg: string;
}
export interface ImageProps {
  _id?: string;
  url?: string;
  fitUrl?: string;
}
export interface ColumnProps {
  _id: string;
  title: string;
  avatar?: ImageProps;
  description: string;
  createdAt: string;
}

export interface UserProps {
  email?: string;
  nickName?: string;
  _id?: string;
  column?: string;
  description?: string;
  avatar?: ImageProps;
  isLogin: boolean;
}

export interface PostProps {
  _id?: string;
  title: string;
  column: string;
  author: string | UserProps;
  key?: number;
  excerpt?: string;
  content?: string;
  createdAt?: string;
  image?: ImageProps | string;
  isHTML?: boolean;
}

export interface GlobalErrorProps {
  status: boolean;
  message?: string;
}
export interface GlobalDataProps {
  error: GlobalErrorProps;
  token: string;
  columns: ColumnProps[];
  posts: PostProps[];
  user: UserProps;
  loading: boolean;
}
export interface patchRequestConfig {
  method?: string;
  data: {
    payload: object;
    id: string
  }
}
async function getAndCommit (url: string, params: object, mutationName: string, commit: Commit) {
  const { data } = await request({
    url,
    method: 'get',
    params
  })
  commit(mutationName, data)
  return data
}
async function postAndCommit (url: string, data: object, mutationName: string, commit: Commit) {
  const { data: rowData } = await request({
    url,
    method: 'post',
    data
  })
  commit(mutationName, rowData)
  return rowData
}
async function asyncAndCommit (url: string, data: patchRequestConfig, mutationName: string, commit: Commit) {
  const { data: rowData } = await request({
    url,
    method: data.method || 'post',
    data: data.data.payload || {}
  })
  commit(mutationName, rowData)
  return rowData
}
const store = createStore<GlobalDataProps>({
  state: {
    error: { status: false },
    token: localStorage.getItem('token') || '',
    columns: [],
    posts: [],
    user: {
      isLogin: false
    },
    loading: false
  },
  mutations: {
    CREATEPOST (state, payload) {
      state.posts.push(payload.data)
    },
    UPDATE_POST (state, payload) {
      state.posts = state.posts.map(post => {
        if (post._id === payload.data._id) {
          return payload.data
        } else {
          return post
        }
      })
    },
    DELETE_POST (state, payload) {
      state.posts = state.posts.filter(post => post._id !== payload.data._id)
    },
    FETCH_COLUMNS (state, payload) {
      state.columns = payload.data.list
    },
    FETCH_COLUMN (state, payload) {
      state.columns = [payload.data]
    },
    FETCH_POSTS (state, payload) {
      state.posts = payload.data.list
    },
    FETCH_POST (state, payload) {
      state.posts.push(payload.data)
    },
    SET_LOADING (state, payload) {
      state.loading = payload
    },
    SET_TOKEN (state, payload) {
      state.token = payload.data.token
      localStorage.setItem('token', payload.data.token)
    },
    SET_USER (state, payload) {
      state.user = { isLogin: true, ...payload.data }
    },
    SET_ERROR (state, e: GlobalErrorProps) {
      state.error = e
    },
    LOGOUT (state) {
      state.token = ''
      state.user = {
        isLogin: false
      }
      localStorage.removeItem('token')
    }
  },
  actions: {
    fetchColumns (context) {
      getAndCommit('/api/columns', {
        currentPage: 1,
        pageSize: 100
      }, 'FETCH_COLUMNS', context.commit)
    },
    fetchColumn (context, payload) {
      getAndCommit(`/api/columns/${payload}`, {}, 'FETCH_COLUMN', context.commit)
    },
    fetchPosts (context, payload) {
      getAndCommit(`/api/columns/${payload}/posts`, {
        currentPage: 1,
        pageSize: 5
      }, 'FETCH_POSTS', context.commit)
    },
    fetchCurrentUser ({ commit }) {
      return getAndCommit('/api/user/current', {}, 'SET_USER', commit)
    },
    createPost ({ commit }, data) {
      return postAndCommit('/api/posts', data, 'CREATEPOST', commit)
    },
    updatePost ({ commit }, data) {
      return asyncAndCommit(`/api/posts/${data.data.id}`, data, 'UPDATE_POST', commit)
    },
    login (context, data) {
      return postAndCommit('/api/user/login', data, 'SET_TOKEN', context.commit)
    },
    loginAndGetUser ({ dispatch }, loginData) {
      return dispatch('login', loginData).then(res => {
        return dispatch('fetchCurrentUser')
      })
    },
    fetchPost ({ state, commit }, _id) {
      const currentPost = state.posts.filter(post => post._id === _id)[0]
      if (!currentPost || currentPost.excerpt) {
        return getAndCommit(`/api/posts/${_id}`, {}, 'FETCH_POST', commit)
      } else {
        return Promise.resolve({ data: currentPost })
      }
    },
    deletePost ({ commit }, data) {
      return asyncAndCommit(`/api/posts/${data.data.id}`, data, 'DELETE_POST', commit)
    }
  },
  getters: {
    getColumnById (state) {
      return (_id: string) => {
        return state.columns.find((c: ColumnProps) => c._id === _id)
      }
    },
    getPostsById (state) {
      return (_id: string) => {
        return state.posts.filter((post: PostProps) => post.column === _id)
      }
    },
    getCurrentPost: (state) => (currentId: string) => {
      return state.posts.filter(post => post._id === currentId)[0]
    }
  }
})

export default store
